package cn.com.anysdk.oss.factory;

import cn.com.anysdk.oss.api.IOssService;
import cn.com.anysdk.oss.exception.OssException;
import cn.com.anysdk.oss.monitor.OssMonitorManager;
import cn.com.anysdk.oss.monitor.OssOperationContext;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * OSS服务代理工厂
 * 用于创建带有异常处理和监控功能的OSS服务代理
 */
@Slf4j
public class OssServiceProxyFactory {
    /**
     * 创建OSS服务代理
     * @param service 原始OSS服务
     * @return 代理后的OSS服务
     */
    public static IOssService createProxy(IOssService service) {
        return (IOssService) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                new Class<?>[]{IOssService.class},
                new OssServiceInvocationHandler(service)
        );
    }

    private static class OssServiceInvocationHandler implements InvocationHandler {
        private final IOssService target;

        public OssServiceInvocationHandler(IOssService target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            OssOperationContext context = OssOperationContext.builder()
                    .provider(getProvider(target.getClass().getSimpleName()))
                    .operationType(getOperationType(method.getName()))
                    .build();

            try {
                Object result = method.invoke(target, args);
                return result;
            } catch (Exception e) {
                Throwable cause = e.getCause();
                if (cause instanceof OssException) {
                    OssMonitorManager.getInstance().notifyListeners((OssException) cause, context);
                    throw cause;
                } else {
                    OssException ossException = new OssException("Operation failed: " + e.getMessage(), e);
                    OssMonitorManager.getInstance().notifyListeners(ossException, context);
                    throw ossException;
                }
            }
        }

        private OssOperationContext.Provider getProvider(String className) {
            if (className.contains("Aliyun")) {
                return OssOperationContext.Provider.ALIYUN;
            } else if (className.contains("Tencent")) {
                return OssOperationContext.Provider.TENCENT;
            } else if (className.contains("Qiniu")) {
                return OssOperationContext.Provider.QINIU;
            } else {
                return OssOperationContext.Provider.LOCAL;
            }
        }

        private OssOperationContext.OperationType getOperationType(String methodName) {
            switch (methodName) {
                case "uploadFile":
                    return OssOperationContext.OperationType.UPLOAD;
                case "downloadFile":
                    return OssOperationContext.OperationType.DOWNLOAD;
                case "deleteFile":
                case "deleteFiles":
                    return OssOperationContext.OperationType.DELETE;
                case "getFileUrl":
                    return OssOperationContext.OperationType.GET_URL;
                case "getSignedUrl":
                    return OssOperationContext.OperationType.GET_SIGNED_URL;
                case "doesObjectExist":
                    return OssOperationContext.OperationType.CHECK_EXIST;
                default:
                    return null;
            }
        }
    }
}